
package cn.com.pusai.common.util;

import cn.com.pusai.core.util.StringUtil;
import java.util.*;
import java.util.regex.Pattern;
import org.hibernate.Query;

public class SearchMap implements Iterable
{
	
	
	public class SearchParameter
	{

		private String key;
		private String name;
		private Object value;
		private String type;
		private String alias;
		final SearchMap this_$0;

		public String toHQL()
		{
			StringBuffer sb = new StringBuffer();
			if (type.equals("TYPE_BETWEEN"))
				sb.append("");
			else
			if (type.equals("in") || type.equals("not in"))
			{
				sb.append(key);
				sb.append(" ");
				sb.append(type);
				sb.append("(").append(value).append(")");
			} else
			{
				if (value != null)
					if (value instanceof String)
					{
						String tempValue = StringUtil.trimToEmpty((String)value).replaceAll("%", "");
						if ("like".equals(type) && tempValue.length() == 0)
							return null;
						sb.append(key);
					} else
					{
						sb.append(key);
					}
				sb.append(" ");
				sb.append(type);
				sb.append(":");
				sb.append(name);
			}
			return sb.toString();
		}

		public void setQuery(Query query)
		{
			if (type.equals("in") || type.equals("not in"))
				return;
			if (value != null)
				if (value instanceof String)
				{
					String tempValue2 = StringUtil.trimToEmpty((String)value).replaceAll("%", "");
					if ("like".equals(type) && tempValue2.length() == 0)
						return;
					String tempValue = (String)value;
					query.setString(name, tempValue);
				} else
				{
					query.setParameter(name, value);
				}
		}

		public String getKey()
		{
			return key;
		}

		public String getType()
		{
			return type;
		}

		public Object getValue()
		{
			return value;
		}

		public String getName()
		{
			return name;
		}

		public void setName(String name)
		{
			this.name = name;
		}

		public String getAlias()
		{
			return alias;
		}

		public SearchParameter(String key, String name, Object value, String type)
		{
			this_$0 = SearchMap.this;
			this.key = key;
			this.name = name;
			this.value = value;
			this.type = type;
			//super();
		}

		public SearchParameter(String key, String name, Object value, String type, String alias)
		{
			this_$0 = SearchMap.this;
			//super();
			this.key = key;
			this.name = name;
			this.value = value;
			this.type = type;
			this.alias = alias;
		}
	}


	public static final String TYPE_LIKE = "like";
	private static final String TYPE_NOT_LIKE = "not like";
	public static final String TYPE_EQUAL = "=";
	private static final String TYPE_NOT_EQUAL = "<>";
	public static final String TYPE_BETWEEN = "TYPE_BETWEEN";
	public static final String TYPE_GREATER = ">";
	public static final String TYPE_GREATER_EQUAL = ">=";
	public static final String TYPE_LESS = "<";
	public static final String TYPE_LESS_EQUAL = "<=";
	private static final String TYPE_NOT_IN = "not in";
	private static final String TYPE_IN = "in";
	public static final String ORDER_DESC = "DESC";
	public static final String ORDER_ASC = "ASC";
	private List orderList;
	private List searchParameterList;
	private Map searchParameterMap;
	private Map nameMap;
	private String aliasTemplete;

	public SearchMap()
	{
		orderList = new ArrayList();
		searchParameterList = new ArrayList();
		searchParameterMap = new HashMap();
		nameMap = new HashMap();
	}

	public void addOrder(String order, String orderType)
	{
		orderList.add(new String[] {
			order, orderType
		});
	}

	public void addOrder(String order)
	{
		addOrder(order, null);
	}

	public Object getValue(String key)
	{
		Object returnValue = null;
		Object object = searchParameterMap.get(key);
		if (object instanceof SearchParameter)
			returnValue = ((SearchParameter)object).getValue();
		else
		if (object instanceof SearchParameter[])
		{
			SearchParameter searchParameter[] = (SearchParameter[])object;
			Object returnValues[] = new Object[searchParameter.length];
			for (int i = 0; i < searchParameter.length; i++)
				returnValues[i] = searchParameter[i].getValue();

			returnValue = ((Object) (returnValues));
		}
		return returnValue;
	}

	public void remove(String key)
	{
		Object object = searchParameterMap.get(key);
		if (object instanceof SearchParameter)
			searchParameterList.remove(object);
		else
		if (object instanceof SearchParameter[])
		{
			SearchParameter searchParameter[] = (SearchParameter[])object;
			for (int i = 0; i < searchParameter.length; i++)
				searchParameterList.remove(searchParameter[i]);

		}
		searchParameterMap.remove(key);
	}

	public void like(String key, Object value)
	{
		add(key, value, "like", null);
	}

	public void like(String key, Object value, String alias)
	{
		add(key, value, "like", alias);
	}

	public void notLike(String key, Object value)
	{
		add(key, value, "not like", null);
	}

	public void notLike(String key, Object value, String alias)
	{
		add(key, value, "not like", alias);
	}

	public void in(String key, String value)
	{
		add(key, value, "in", null);
	}

	public void notIn(String key, String value)
	{
		add(key, value, "not in", null);
	}

	/**
	 * 介意**之间(between)
	 * @param key 查询参数名
	 * @param valueBegin  开始参数值
	 * @param  valueEnd 结束参数值
	 * */
	public void between(String key, String valueBegin, String valueEnd)
	{
		ge(key, valueBegin);
		le(key, valueEnd);
	}
	
	/**
	 * 介意**之间(between)
	 * @param key 查询参数名
	 * @param valueBegin  开始参数值
	 * @param  valueEnd 结束参数值
	 * @param alias 别名
	 * */
	public void between(String key, String valueBegin, String valueEnd, String alias)
	{
		ge(key, valueBegin, alias);
		le(key, valueEnd, alias);
	}
	
	/**
	 * 等于(=)
	 * @param key 查询参数名
	 * @param value 参数值
	 * */
	public void eq(String key, Object value)
	{
		add(key, value, "=", null);
	}
	
	
	/**
	 * 等于(=)
	 * @param key 查询参数名
	 * @param value 参数值
	 * @param alias 别名
	 * */
	public void eq(String key, Object value, String alias)
	{
		add(key, value, "=", alias);
	}
	
	/**
	 * 大于等于(>=)
	 * @param key 查询参数名
	 * @param value 参数值
	 * */
	public void ge(String key, Object value)
	{
		add(key, value, ">=", null);
	}

	/**
	 * 大于等于(>=)
	 * @param key 查询参数名
	 * @param value 参数值
	 * @param alias 别名
	 * */
	public void ge(String key, Object value, String alias)
	{
		add(key, value, ">=", alias);
	}

	/**
	 * 大于(>)
	 * @param key 查询参数名
	 * @param value 参数值
	 * */

	public void gt(String key, Object value)
	{
		add(key, value, ">", null);
	}
	
	/**
	 * 大于等于(>=)
	 * @param key 查询参数名
	 * @param value 参数值
	 * @param alias 别名
	 * */

	public void gt(String key, Object value, String alias)
	{
		add(key, value, ">", alias);
	}

	/**
	 * 小于等于(<=)
	 * @param key 查询参数名
	 * @param value 参数值
	 * */
	public void le(String key, Object value)
	{
		add(key, value, "<=", null);
	}

	/**
	 * 小于等于(<=)
	 * @param key 查询参数名
	 * @param value 参数值
	 * @param alias 别名
	 * */
	public void le(String key, Object value, String alias)
	{
		add(key, value, "<=", alias);
	}

	/**
	 * 不等于(<>)
	 * @param key 查询参数名
	 * @param value 参数值
	 * */
	public void notEq(String key, Object value)
	{
		add(key, value, "<>", null);
	}

	/**
	 * 不等于(<>)
	 * @param key 查询参数名
	 * @param value 参数值
	 * @param alias 别名
	 * */
	public void notEq(String key, Object value, String alias)
	{
		add(key, value, "<>", alias);
	}
	
	/**
	 * 小于(<)
	 * @param key 查询参数名
	 * @param value 参数值 
	 * */
	public void lt(String key, Object value)
	{
		add(key, value, "<", null);
	}

	/**
	 * 小于(<)
	 * @param key 查询参数名
	 * @param value 参数值 
	 * @param alias 别名
	 * */
	public void lt(String key, Object value, String alias)
	{
		add(key, value, "<", alias);
	}

	public String getAliasTemplete()
	{
		return aliasTemplete;
	}

	public void setAliasTemplete(String aliasTemplete)
	{
		this.aliasTemplete = (new StringBuilder("( ")).append(aliasTemplete).append(" )").toString();
	}

	private void add(String key, Object value, String type, String alias)
	{
		String tempKey = key;
		if (tempKey != null && tempKey.indexOf(".") >= 0)
			tempKey = tempKey.substring(tempKey.lastIndexOf(".") + 1);
		Integer count = (Integer)nameMap.get(tempKey);
		if (count != null && count.intValue() > 0)
		{
			nameMap.put(tempKey, new Integer(count.intValue() + 1));
			tempKey = (new StringBuilder(String.valueOf(tempKey))).append(count.intValue() + 1).toString();
		} else
		{
			nameMap.put(tempKey, new Integer(1));
		}
		SearchParameter searchParameter = new SearchParameter(key, tempKey, value, type, alias);
		searchParameterList.add(searchParameter);
		Object searchParameterObject = searchParameterMap.get(key);
		if (searchParameterObject != null)
		{
			if (searchParameterObject instanceof SearchParameter)
			{
				SearchParameter tempSearchParameter[] = new SearchParameter[2];
				tempSearchParameter[0] = (SearchParameter)searchParameterObject;
				tempSearchParameter[1] = searchParameter;
			} else
			if (searchParameterObject instanceof SearchParameter[])
			{
				SearchParameter oldSearchParameter[] = (SearchParameter[])searchParameterObject;
				SearchParameter tempSearchParameter[] = new SearchParameter[oldSearchParameter.length + 1];
				for (int i = 0; i < oldSearchParameter.length; i++)
					tempSearchParameter[i] = oldSearchParameter[i];

				tempSearchParameter[oldSearchParameter.length] = searchParameter;
			}
		} else
		{
			searchParameterMap.put(key, searchParameter);
		}
	}

	public Iterator iterator()
	{
		return searchParameterList.iterator();
	}

	public String toHQL()
	{
		StringBuffer sb = new StringBuffer("");
		Iterator it = iterator();
		Map templeteHQL = new HashMap();
		while (it.hasNext()) 
		{
			SearchParameter searchParameter = (SearchParameter)it.next();
			Object value = searchParameter.getValue();
			if (value != null)
				if ((value instanceof String) && ((String)value).length() <= 0)
				{
					if (StringUtil.isNotEmpty(searchParameter.getAlias()) && getAliasTemplete().indexOf(searchParameter.getAlias()) != -1)
						templeteHQL.put(searchParameter.getAlias(), " 1 = 1");
				} else
				if (StringUtil.isEmpty(getAliasTemplete()) || StringUtil.isEmpty(searchParameter.getAlias()))
				{
					String hql = searchParameter.toHQL();
					if (hql != null && hql.length() > 0)
					{
						if (sb.toString().length() > 0)
							sb.append(" and ");
						sb.append(hql);
					}
				} else
				if (getAliasTemplete().indexOf(searchParameter.getAlias()) == -1)
				{
					String hql = searchParameter.toHQL();
					if (hql != null && hql.length() > 0)
					{
						if (sb.toString().length() > 0)
							sb.append(" and ");
						sb.append(hql);
					}
				} else
				{
					templeteHQL.put(searchParameter.getAlias(), searchParameter.toHQL());
				}
		}
		if (StringUtil.isNotEmpty(getAliasTemplete()) && !templeteHQL.isEmpty())
		{
			Iterator aliasKeys = templeteHQL.keySet().iterator();
			String tempHQL = getAliasTemplete();
			while (aliasKeys.hasNext()) 
			{
				String tempAlias = (String)aliasKeys.next();
				if (StringUtil.isEmpty((String)templeteHQL.get(tempAlias)))
					tempHQL = tempHQL.replaceAll(Pattern.quote(tempAlias), " 1 = 1 ");
				else
					tempHQL = tempHQL.replaceAll(Pattern.quote(tempAlias), (String)templeteHQL.get(tempAlias));
			}
			if (sb.toString().length() > 0)
				sb.append(" and ");
			sb.append(tempHQL);
		}
		return sb.toString();
	}

	public void setQuery(Query query)
	{
		for (Iterator it = iterator(); it.hasNext();)
		{
			SearchParameter searchParameter = (SearchParameter)it.next();
			Object value = searchParameter.getValue();
			if (value != null)
				if (value instanceof String)
				{
					if (((String)value).length() > 0)
						searchParameter.setQuery(query);
				} else
				{
					searchParameter.setQuery(query);
				}
		}

	}

	public List getOrderList()
	{
		return orderList;
	}
}
